﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Test.Formatting
{

    public class MyAssert
    {


        public static void Throws<T>(Action action, string expectedMessage) where T : Exception
        {
            try
            {
                action.Invoke();

                Assert.Fail("Exception of type {0} should be thrown.", typeof(T));
            }
            catch (T exc)
            {
                Assert.AreEqual(expectedMessage, exc.Message);
            }
        }

        /// <summary>
        /// Checks to make sure that the input delegate throws a exception of type TException.
        /// </summary>
        /// <typeparam name="TException">The type of exception expected.</typeparam>
        /// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
        public static void Throws<TException>(Action blockToExecute) where TException : System.Exception
        {
            try
            {
                blockToExecute();
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
                return;
            }

            Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
        }

        /// <summary>
        /// Checks to make sure that the input delegate throws a exception of type TException.
        /// </summary>
        /// <typeparam name="TException">The type of exception expected.</typeparam>
        /// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
        public static void Throws<TException>(string expectedMessage, Action blockToExecute) where TException : System.Exception
        {
            try
            {
                blockToExecute();
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
                Assert.AreEqual(expectedMessage, ex.Message, "Expected exception with a message of '" + expectedMessage + "' but exception with message of '" + ex.Message + "' was thrown instead.");
                return;
            }

            Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
        }


    }


}

//Then all I needed to do is use the new class whenever I needed to test for an exception and verify its message:
//[TestMethod]
//public void AddNewUser_UserEmailIsEmpty_ThrowException()
//{
//    MyAssert.Throws<ApplicationException>(
//        () => UserConnector.AddNewUser("user1", ""),
//        "Error: user's email address missing");
//}
//Although this solution seems mo
//}

/// <summary>
/// Contains assertion types that are not provided with the standard MSTest assertions.
/// </summary>
internal static class ExceptionAssert
{
    /// <summary>
    /// Checks to make sure that the input delegate throws a exception of type TException.
    /// </summary>
    /// <typeparam name="TException">The type of exception expected.</typeparam>
    /// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
    public static void Throws<TException>(Action blockToExecute) where TException : System.Exception
    {
        try
        {
            blockToExecute();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
            return;
        }

        Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
    }

    /// <summary>
    /// Checks to make sure that the input delegate throws a exception of type TException.
    /// </summary>
    /// <typeparam name="TException">The type of exception expected.</typeparam>
    /// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
    public static void Throws<TException>(string expectedMessage, Action blockToExecute) where TException : System.Exception
    {
        try
        {
            blockToExecute();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
            Assert.AreEqual(expectedMessage, ex.Message, "Expected exception with a message of '" + expectedMessage + "' but exception with message of '" + ex.Message + "' was thrown instead.");
            return;
        }

        Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
    }
}